package cHelper

import (
	"context"
	"fmt"
	"os"
	"os/exec"
	"regexp"
	"runtime"
	"strings"
	"time"
)

type MemoryStatus struct {
	Pid  int
	Used int
	G    string
	M    string
	K    string
	Err  error
}

func PrintMemory(ctx context.Context, interval int64, handle func(ctx context.Context, mem *MemoryStatus)) {
	msg := make(chan *MemoryStatus)
	ticker := time.NewTicker(time.Duration(interval) * time.Second)

	go func(ctx context.Context, handle func(ctx context.Context, mem *MemoryStatus), msg chan *MemoryStatus) {
		for { //nolint:gosimple
			select {
			case mem := <-msg:
				handle(ctx, mem)
			}
		}
	}(ctx, handle, msg)

	go func(ticker *time.Ticker, msg chan *MemoryStatus) {
		for { //nolint:gosimple
			select {
			case <-ticker.C:
				switch runtime.GOOS {
				case "linux":
					pid := os.Getpid()
					processFile := fmt.Sprintf("/proc/%d/status", pid)
					detail, err := os.ReadFile(processFile)
					var res int
					if err != nil {
						msg <- &MemoryStatus{
							Pid: pid,
							Err: err,
						}
						continue
					}
					reg := regexp.MustCompile(`VmRSS[^\d]*([0-9]*)`)
					mem := reg.FindAllStringSubmatch(string(detail), -1)
					res = ToInt(mem[0][1])
					msg <- &MemoryStatus{
						Pid:  pid,
						Used: res,
						G:    fmt.Sprintf("%.2f GB", float64(res)/float64(1024)/float64(1024)),
						M:    fmt.Sprintf("%d MB", res/1024),
						K:    fmt.Sprintf("%d KB", res),
						Err:  err,
					}
				case "windows":
					pid := os.Getpid()
					command := fmt.Sprintf("wmic process where processid=%d get WorkingSetSize", pid)
					commands := strings.Split(command, " ")
					cmd := exec.Command(commands[0], commands[1:]...)
					var res int
					detail, err := cmd.Output()
					if err != nil {
						msg <- &MemoryStatus{
							Pid: pid,
							Err: err,
						}
						continue
					}
					reg := regexp.MustCompile(`([0-9]+)`)
					mem := reg.FindAllString(string(detail), -1)
					res = ToInt(string(mem[0]))
					msg <- &MemoryStatus{
						Pid:  pid,
						Used: res,
						G:    fmt.Sprintf("%.2f GB", float64(res)/float64(1024)/float64(1024)/float64(1024)),
						M:    fmt.Sprintf("%d MB", res/1024/1024),
						K:    fmt.Sprintf("%d KB", res/1024),
						Err:  err,
					}
				}
			}
		}

	}(ticker, msg)
}
